package com.atwisdom.star.core.bsl.planner.Impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.atwisdom.star.common.vo.ModelType;
import com.atwisdom.star.core.bsl.planner.StockDetailBslService;
import com.atwisdom.star.core.bsl.planner.entity.Stock;
import com.atwisdom.star.core.bsl.planner.entity.Warehouse;
import com.atwisdom.star.core.dao.pojo.modelClass.hier.HierInstance;
import com.atwisdom.star.core.dsl.modelClass.hier.HierInstanceDslService;
import com.atwisdom.star.core.dsl.modelClass.logic.Impl.LogicInstanceDslServiceImpl;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

@Service
@Data
@NoArgsConstructor
public class StockDetailBslServiceImpl implements StockDetailBslService {

    private LogicInstanceDslServiceImpl logicInstanceDslService;
    private HierInstanceDslService hierInstanceDslService;

    @Autowired
    public void setLogicInstanceDslService(LogicInstanceDslServiceImpl logicInstanceDslService) {
        this.logicInstanceDslService = logicInstanceDslService;
    }

    @Autowired
    public void setHierInstanceDslService(HierInstanceDslService hierInstanceDslService) {
        this.hierInstanceDslService = hierInstanceDslService;
    }

    //库存信息
    private List<Stock> stocks = new ArrayList<>();
    //初始化全局库存量，初始化后不会再改变
    private Map<String, Double> initStockMap = new HashMap<>();
    //全局全局库存量，在MRP运算过程，根据在途、在制等会被改变，作为临时缓存用
    private Map<String, Double> stockMap = new HashMap<>();
    //有效仓库列表
    private List<Warehouse> warehouseList = new ArrayList<>();

    @Override
    public void initWarehouse(String condition){
        this.warehouseList = new ArrayList<>();
        List<HierInstance> warehouseHierInsList = this.hierInstanceDslService.query(ModelType.Twins.getCode(), "warehouse", condition);
        warehouseHierInsList.forEach(hIns -> {
            Warehouse warehouse = new Warehouse();
            JSONObject values = hIns.getValues();
            //仓库id
            warehouse.setId(hIns.getId());
            //仓库编码
            warehouse.setCode(values.getString("code"));
            //仓库名称
            warehouse.setName(values.getString("name"));
            //仓库位置
            warehouse.setLocation(values.getString("location"));
            //是否参与运算
            warehouse.setComputeFlag(values.getBoolean("computeFlag"));
            //不良品库
            warehouse.setDefectiveFlag(values.getBoolean("defectiveFlag"));
            //是否为废品库
            warehouse.setWasterFlag(values.getBoolean("wasterFlag"));
            //线边仓
            warehouse.setLineFlag(values.getBoolean("lineFlag"));
            this.warehouseList.add(warehouse);
        });
    }

    /**
     * 执行MRP运算初始化库存
     */
    @Override
    public void initMrpStock() {
        this.stockMap = new HashMap<>();
        this.initStockMap = new HashMap<>();
        this.initWarehouse(" computeFlag = 1 ");
        List<String>  warehouseIdList = this.warehouseList.stream().map(Warehouse::getId).map(m -> m + "").collect(toList());
        String stockCondition = "";
        if (CollectionUtil.isNotEmpty(warehouseIdList)) {
            String joinIds = String.join(",", warehouseIdList);
            stockCondition = String.format(" available_quantity > 0 and stock_type = 1 and status <> 9 and warehouse_id in (%s) ", joinIds);
        }
        this.initStock(stockCondition);
    }

    /**
     * 执行工单齐套分析运算初始化库存
     */
    @Override
    public void initCompleteAnalysisStock(String condition) {
        this.initStockMap = new HashMap<>();
        this.stockMap = new HashMap<>();
        String stockCondition = this.getWarehouseStockCondition();
        stockCondition = StringUtils.isBlank(condition) ? stockCondition : stockCondition + " and " + condition;
        this.initStock(stockCondition);
    }

    /**
     * 获取有可进行齐套分析的有效他库
     * @return 查询有效仓库库存查询条件
     */
    private String getWarehouseStockCondition(){
        this.initWarehouse(" defectiveFlag = 0 and wasterFlag =0  and waitCheckFlag = 0 ");
        List<String>  warehouseIdList = this.warehouseList.stream().map(Warehouse::getId).filter(Objects::nonNull).map(m -> m + "").collect(toList());
        String stockCondition = " 1 = 1 ";
        if (CollectionUtil.isNotEmpty(warehouseIdList)) {
            String joinIds = String.join(",", warehouseIdList);
            stockCondition = String.format(" available_quantity > 0 and stock_type = 1 and status =1 and warehouse_id in (%s) ", joinIds);
        }
        return stockCondition;
    }

    private void initStock(String condition) {
        this.stocks = new ArrayList<>();
        List<JSONObject> stockList = this.logicInstanceDslService.query(condition, "stockDetail");
        for (JSONObject jsonObject : stockList) {
            JSONObject values = jsonObject.getJSONObject("values");
            String pCode = values.getString("material_pcode");
            String bCode = values.getString("material_bcode");
            String model = values.getString("material_model");
            String spec = values.getString("material_spec");
            Double quantity = values.getDouble("available_quantity") == null ? 0 : values.getDouble("available_quantity");
            Double subQuantity = values.getDouble("available_subQuantity") == null ? 0 : values.getDouble("available_subQuantity");
            String materialUnit = values.getString("material_unit");
            Double price = values.getDouble("price");
            Double weight = values.getDouble("weight");
            String warehouseCode = values.getString("warehouse_code");
            Integer warehouseId = values.getInteger("warehouse_id");
            String binCode = values.getString("bin_code");
            Integer binId = values.getInteger("bin_id");
            Stock stock = new Stock();
            stock.setMaterialPCode(pCode);
            stock.setMaterialBCode(bCode);
            stock.setMaterialModel(model);
            stock.setMaterialSpec(spec);
            stock.setQuantity(quantity);
            stock.setSubQuantity(subQuantity);
            stock.setMaterialUnit(materialUnit);
            stock.setPrice(price);
            stock.setWeight(weight);
            stock.setWarehouseCode(warehouseCode);
            stock.setWarehouseId(warehouseId);
            stock.setBinCode(binCode);
            stock.setBinId(binId);
            stocks.add(stock);
        }
        this.initStockMap = stocks.stream().collect(Collectors.groupingBy(Stock::getMaterialBCode, Collectors.summingDouble(Stock::getQuantity)));
    }
}


